package gatech.cs2340.adventuretime.server;


import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import com.db4o.Db4oEmbedded;
import com.db4o.EmbeddedObjectContainer;
import com.db4o.ObjectContainer;

import gatech.cs2340.adventuretime.client.Client;
import gatech.cs2340.adventuretime.client.HtmlRoutine;
import gatech.cs2340.adventuretime.persistent.users.User;
import gatech.cs2340.adventuretime.server.*;

/**
 * I see this class handling the first request param "handler" and then passing the rest of the params/data on to the appropriate handler 
 * This way we could separate the UI logic a bit further from the db code. I may combine handlers and this servlet into one adventuretime.server package
 * @author Win
 *
 */

public class FrontServlet extends HttpServlet implements ServletContextListener
{
	
    private Hashtable           _postHandlers = new Hashtable(100);
    private Hashtable           _getHandlers = new Hashtable(100);

    private Object[]            _services;
    private PrintStream         _log;
    private HtmlRoutine         _routine = new HtmlRoutine();

    //private RequestHandler      _searchByIdH;
    private RequestHandler      _loginH;
    private RequestHandler      _showProfilePageHandler;
    //private RequestHandler      _showResultH;
    
    private RequestHandler      _logoutH;
    //private RequestHandler      _disconnectH;
    //private RequestHandler      _reloadH;

    private String              _msg = "";

    /**
     * init method
     */
    public void init(ServletConfig config) throws ServletException
    {

        super.init(config);

        try
        {
            //First: get service references
            _services = new Object[2];
    
            ObjectContainer db = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),"testDB4O");
            _services[0] = db;
            //Second: init RequestHandlers
            _loginH = new LoginH();
            //_showResultH = new ShowResultH();
            //_searchByIdH = new SearchByIdH();
            
            RequestHandler showProfilePage = new showProfilePageH();
            _logoutH = new LogoutH();
            //_disconnectH = new DisconnectH();
            //_reloadH = new ReloadH();

            //Third: put RequestHandlers in place
            addPostRequestHandler("login", _loginH);
            addPostRequestHandler("showProfilePage", showProfilePage);
            //addPostRequestHandler("showResult", _showResultH);
            //addPostRequestHandler("searchById", _searchByIdH);

            addGetRequestHandler("logout", _logoutH);
            //addGetRequestHandler("disconnect", _disconnectH);
            //addGetRequestHandler("reload", _reloadH);
        }
        catch(Exception e)
        {
            _msg = _msg+ "init() failed. "+e.getMessage();
            System.out.println(_msg);
        }
    }

    public void destroy()
    {
        //First: release resources and clean up
        
        super.destroy();
        System.out.println("\n"+Client.getCurrentLocalTimeStr()+" - XXXXX servlet destroyed.");
    }

    public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {

        //Set output HTML content type
        res.setContentType("text/html");

        //Get output stream
        ServletOutputStream out = res.getOutputStream();

        String handlerName = req.getParameter("handler");
        if(handlerName.equals("login"))
        {
            _loginH.processRequest(null, req, res, _services, _log);
            return;
        }

        HttpSession session = req.getSession(false);
        if(session == null)
        {
            String msg="You have been logged out or your session is timed out. ";
            msg+="Please relogin. <a href=\"" + Client.getLoginPageUrl() + "\">";
            msg+="Goto login page</a>";
            _routine.printMsgPage(out, msg);
            return;
        }

        User user = (User)session.getValue("gatech.cs2340.adventuretime.user");
        RequestHandler handler = getPostRequestHandler(handlerName);
        if(handler == null)
        {
            String msg="Unregistered POST request. ";
            _routine.printMsgPage(out, msg);
            return;
        }

        handler.processRequest(user, req, res, _services, _log);
        return;
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {

        //Set output HTML content type
        res.setContentType("text/html");

        //Get output stream
        ServletOutputStream out = res.getOutputStream();

        HttpSession session = req.getSession(false);

        if(session == null)
        {
            String msg="You have been logged out or your session is timed out. ";
            msg+="Please relogin. <a href=\"" + Client.getLoginPageUrl() + "\">";
            msg+="Goto login page</a>";
            _routine.printMsgPage(out, msg);
            return;
        }

        User user = (User)session.getValue("article.user");
        String query = req.getQueryString();
        String handlerName = getGetRequestHandler(query).toString();
        RequestHandler handler = getPostRequestHandler(handlerName);
        if(handler == null)
        {
            String msg="Unregistered GET request. ";
            _routine.printMsgPage(out, msg);
            return;
        }

        handler.processRequest(user, req, res, _services, _log);
        return;
    }

    public void addPostRequestHandler(String name, RequestHandler handler)
    {
        _postHandlers.put(name, handler);
    }

    public void removePostRequestHandler(String name)
    {
        _postHandlers.remove(name);
    }

    public void removeAllPostRequestHandlers()
    {
        _postHandlers.clear();
    }

    public void addGetRequestHandler(String name, RequestHandler handler)
    {
        _getHandlers.put(name, handler);
    }

    public void removeGetRequestHandler(String name)
    {
        _getHandlers.remove(name);
    }

    public void removeAllGetRequestHandlers()
    {
        _getHandlers.clear();
    }

    private RequestHandler getPostRequestHandler(String name)
    {
        return (RequestHandler)_postHandlers.get(name);
    }

    private RequestHandler getGetRequestHandler(String name)
    {
        return (RequestHandler)_getHandlers.get(name);
    }

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		ServletContext context = event.getServletContext();
		String filePath = context.getRealPath("WEB-INF/"
				+ context.getInitParameter(KEY_DB4O_FILE_NAME));
		EmbeddedObjectContainer rootContainer = Db4oEmbedded.openFile(filePath);
		context.setAttribute(KEY_DB4O_SERVER, rootContainer); context.log("db4o startup on " + filePath);
		
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}
